/*****************************************************
*                                                                          
*               COPYRIGHT (c) 2015-2017 Hargic Corporation              
*                         All Rights Reserved                              
*                                                                          
* The source code contained or described herein and all documents          
* related to the source code ("Material") are owned by Hargic         
* Corporation or its licensors.  Title to the Material remains             
* with Hargic Corporation or its suppliers and licensors.               
*                                                                          
* The Material is protected by worldwide copyright and trade secret        
* laws and treaty provisions. No part of the Material may be used,         
* copied, reproduced, modified, published, uploaded, posted, transmitted,  
* distributed, or disclosed in any way except in accordance with the       
* applicable license agreement.                                            
*                                                                          
* No license under any patent, copyright, trade secret or other            
* intellectual property right is granted to or conferred upon you by       
* disclosure or delivery of the Materials, either expressly, by            
* implication, inducement, estoppel, except in accordance with the         
* applicable license agreement.                                            
*                                                                          
* Unless otherwise agreed by Hargic in writing, you may not remove or   
* alter this notice or any other notice embedded in Materials by Hargic 
* or Hargic's suppliers or licensors in any way.                        
*                                                                          
** Author: ted.huang
** Date: 2018-03-08
*
*****************************************************/

/***** Include files ********************************/
#include "protocol.h"
#include "version.h"
#include <string.h>

/***** Defines **************************************/

/***** Define structure *****************************/

/***** Define constant ******************************/

/***** Define global ********************************/
uint8_t send_buffer[WIRELESS_SEND_BUFFER_SIZE];
uint8_t recv_buffer[WIRELESS_RECV_BUFFER_SIZE];

/***** Define Prototype of functions ****************/
static uint16_t calc_checksum(uint8_t *data, uint16_t len);
static int8_t is_checksum_valid(msg_header_t *head);
static int8_t is_msg_header_valid(msg_header_t *head);

/**
 * @brief
 * @param  None
 * @retval None
 */
uint16_t message_handler(uint8_t *data, uint16_t len)
{
    msg_header_t *head;
    uint16_t consum = 0, msglen;

    if (len >= WIRELESS_RECV_BUFFER_SIZE)
        return 0;

    while (len)
    {
    	// first check message head
    	if (len < MSG_HEADER_SIZEOF)
    		break;

        head = (msg_header_t *)(data + consum);

        if (is_msg_header_valid(head) < 0)
        {
            len--;
            consum++;
            continue;
        }

        // make sure head->len is not too large
        if ((MSG_HEADER_SIZEOF + head->len) >= WIRELESS_RECV_BUFFER_SIZE)
            return 0;

        msglen = MSG_HEADER_SIZEOF + head->len;

        // msg length not enough
        if (len < msglen)
        {
        	if (consum != 0)
            	memcpy(data, data + consum, len);

            break;
        }

        if (is_checksum_valid(head))
            message_process(data + consum, msglen);

        len -= msglen;
        consum += msglen;
    }

    return len;
}

static uint16_t calc_checksum(uint8_t *data, uint16_t len)
{
    uint16_t i, csum;

    csum = MSG_HEADER_CSUM_OFFSET;
    for (i=0; i<len; i++)
        csum += *(data + i);

    return csum;
}

static int8_t is_checksum_valid(msg_header_t *head)
{
    uint8_t *pbuf;
    uint16_t csum_orig, csum_new;

    csum_orig = head->csum;
    head->csum = 0;

    pbuf = (uint8_t *)head;
    csum_new = calc_checksum(pbuf, MSG_HEADER_SIZEOF + head->len);

    return (csum_new == csum_orig);
}

static int8_t is_msg_header_valid(msg_header_t *head)
{
    if (head->magic != MSG_HEADER_MAGIC)
        return -1;

    if (head->pid != PRODUCT_ID_DOOR_MECHINE)
        return -2;

    if (head->did == DEVICE_ID_DOOR_MECHINE_MASTER)
        return -3;

    return 0;
}

int16_t message_send(uint16_t cmd, uint8_t *body, uint16_t bodylen)
{
    msg_header_t *header = (msg_header_t *)send_buffer;
    int16_t msglen = MSG_HEADER_SIZEOF + bodylen;

    if (msglen > WIRELESS_SEND_BUFFER_SIZE)
        return -1;

    memset(header, 0x0, MSG_HEADER_SIZEOF);
    header->magic = MSG_HEADER_MAGIC;
    header->pid = PRODUCT_ID_DOOR_MECHINE;
    header->did = DEVICE_ID_DOOR_MECHINE_MASTER;
    header->cmd = cmd;
    header->len = bodylen;
    header->version = MSG_VERSION;
    memcpy(send_buffer + MSG_HEADER_SIZEOF, body, bodylen);
    header->csum = calc_checksum(send_buffer, msglen);

    return msglen;
}

/* End of file */



